package com.spzx.common.log.aspect;

import com.alibaba.fastjson2.JSON;
import com.spzx.common.log.annotation.PrintLog;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Date;

@Aspect
@Component
@Slf4j
public class PrintLogAspect {

    //    @Around("@annotation(com.spzx.common.log.annotation.PrintLog)")  使用注解全类名编写切入点表达式 在通知方法中还需要手动获取注解对象
    @Around("@annotation(printLog)") //使用形参的类型当作切入点表达式，执行时将目标方法的注解对象作为实参传入
    public Object around(ProceedingJoinPoint joinPoint, PrintLog printLog){//printLog表示目标方法上的注解对象
        try {
            Long start = System.currentTimeMillis();
            //可以获取request对象，再获取请求路径和请求方式: springboot提供的，请求访问后端接口时，它预先会将request对象缓存到RequestContextHolder中
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();

            //1、前置日志打印
            String requestParams = printLog.isPrintRequestParam()? JSON.toJSONString(joinPoint.getArgs() ):"";
            log.info("当前时间:{},访问的模块:{},接口路径:{},请求方式：{},请求参数:{}",
                     new Date() , printLog.title() ,request.getRequestURL(), request.getMethod(),
                     requestParams);
            //2、目标方法执行
            Object result = joinPoint.proceed();
            String requestData = printLog.isPrintResponseData()? JSON.toJSONString(result):"";
            log.info("当前时间:{},响应结果:{}，耗时:{} ms",
                     new Date() , requestData , System.currentTimeMillis() - start);
            return result;

            //3、后置日志的打印
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }


    }
}
